/*
 * Copyright 2002-2006 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jacky.lanlan.song.extension.struts.interceptor;

import java.util.Collections;
import java.util.Comparator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForward;

/**
 * {@link POJOAction} 拦截器，类似 Spring 的 <code>HandlerInterceptor</code>。
 * 
 * @author Jacky.Song
 */
public interface ActionInterceptor {
	
	/**
	 * Intercept the execution of a handler. Called after HandlerMapping determined an appropriate
	 * handler object, but before HandlerAdapter invokes the handler.
	 * <p>
	 * DispatcherServlet processes a handler in an execution chain, consisting of any number of
	 * interceptors, with the handler itself at the end. With this method, each interceptor can decide
	 * to abort the execution chain, typically sending a HTTP error or writing a custom response.
	 * 
	 * @param request
	 *          current HTTP request
	 * @param response
	 *          current HTTP response
	 * @param action
	 *          chosen handler to execute, for type and/or instance evaluation
	 * @return <code>null</code> if the execution chain should proceed with the next interceptor or
	 *         the handler itself. Else, DispatcherServlet assumes that this interceptor has already
	 *         dealt with the response itself.
	 *         <p>
	 *         如果返回非<code>null</code>值，控制器会自动根据返回的字符串寻找ActionForward并返回给 <code>RequestProcessor</code>
	 *         ，拦截器的其他方法将不会被调用。
	 * @throws Exception
	 *           in case of errors
	 */
	String preHandle(HttpServletRequest request, HttpServletResponse response, Object action)
	    throws Exception;

	/**
	 * Intercept the execution of a handler. Called after HandlerAdapter actually
	 * invoked the handler, but before the DispatcherServlet renders the view.
	 * Can expose additional model objects to the view via the given ModelAndView.
	 * <p>DispatcherServlet processes a handler in an execution chain, consisting
	 * of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can post-process an execution,
	 * getting applied in inverse order of the execution chain.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param action chosen action to execute, for type and/or instance examination
	 * @param distination the distination path of this operation
	 * @throws Exception in case of errors
	 */
	void postHandle(HttpServletRequest request, HttpServletResponse response,
			Object action,ActionForward distination)
			throws Exception;

	/**
	 * Callback after completion of request processing, that is, after rendering
	 * the view. Will be called on any outcome of handler execution, thus allows
	 * for proper resource cleanup.
	 * <p>Note: Will only be called if this interceptor's <code>preHandle</code>
	 * method has successfully completed and returned <code>true</code>!
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param action chosen handler to execute, for type and/or instance examination
	 * @param ex exception thrown on handler execution, if any
	 * @throws Exception in case of errors
	 */
	void afterCompletion(
			HttpServletRequest request, HttpServletResponse response, Object action, Exception ex)
			throws Exception;
	
	/**
	 * 设置优先级，正数，值越小优先级越高(即1有最高优先级)。
	 * <p>
	 * 如果有两个拦截器具有相同优先级，则他们的调用顺序是不确定的。
	 * <p>
	 * 具有高优先级的拦截器，其 <code>preHandle()</code> 方法优先调用，而其 <code>postHandle()、afterCompletion()</code>
	 * 方法则后调用。
	 */
	int priority();
	
	/**
	 * 按优先级升序排序，即优先级越高的排列越靠前。
	 */
	Comparator<ActionInterceptor> PRIORITY_ASC=new Comparator<ActionInterceptor>() {
		public int compare(ActionInterceptor o1, ActionInterceptor o2) {
			return o1.priority()-o2.priority();
		}
	};
	
	/**
	 * 按优先级降序排序，即优先级越高的排列越靠后。
	 */
	Comparator<ActionInterceptor> PRIORITY_DESC = Collections.reverseOrder(PRIORITY_ASC);
}
